"""
页面导航管理器

统一管理页面识别和导航流程
"""

import asyncio
import sys
from typing import Dict, Any, Optional, List, Type
from playwright.async_api import Page
from pathlib import Path

# 添加项目根目录到Python路径
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))

try:
    from src.browser.page_handler import BasePageHandler
    from src.browser.page_handlers.page_detector import PageDetector
    from src.browser.page_handlers.popup_handler import PopupHandler
    from src.browser.page_handlers.game_page_handler import GamePageHandler
    from src.browser.page_handlers.download_dialog_handler import DownloadDialogHandler
    from src.browser.page_handlers.password_protected_page_handler import PasswordProtectedPageHandler
    from src.utils.logger import get_logger
    from src.utils.decorators import log_function_call, log_performance
    from src.exceptions.exceptions import PageElementException, NavigationException
except ImportError:
    try:
        from .page_handler import BasePageHandler
        from .page_handlers.page_detector import PageDetector
        from .page_handlers.popup_handler import PopupHandler
        from .page_handlers.game_page_handler import GamePageHandler
        from .page_handlers.download_dialog_handler import DownloadDialogHandler
        from .page_handlers.password_protected_page_handler import PasswordProtectedPageHandler
        from utils.logger import get_logger
        from utils.decorators import log_function_call, log_performance
        from exceptions.exceptions import PageElementException, NavigationException
    except ImportError:
        from browser.page_handler import BasePageHandler
        from browser.page_handlers.page_detector import PageDetector
        from browser.page_handlers.popup_handler import PopupHandler
        from browser.page_handlers.game_page_handler import GamePageHandler
        from browser.page_handlers.download_dialog_handler import DownloadDialogHandler
        from browser.page_handlers.password_protected_page_handler import PasswordProtectedPageHandler
        from utils.logger import get_logger
        from utils.decorators import log_function_call, log_performance
        from exceptions.exceptions import PageElementException, NavigationException

logger = get_logger(__name__)


class PageNavigationManager:
    """页面导航管理器类"""
    
    def __init__(self, page: Page):
        """
        初始化页面导航管理器
        
        Args:
            page: Playwright页面对象
        """
        self.page = page
        self.logger = get_logger(self.__class__.__name__)
        
        # 初始化各种处理器
        self.page_detector = PageDetector(page)
        self.popup_handler = PopupHandler(page)
        self.game_page_handler = GamePageHandler(page)
        self.download_dialog_handler = DownloadDialogHandler(page)
        self.password_protected_page_handler = PasswordProtectedPageHandler(page)
        
        # 页面处理器映射
        self.page_handlers: Dict[str, Type[BasePageHandler]] = {
            'game_page_a': GamePageHandler,
            'game_page_b': GamePageHandler,
            'download_page': GamePageHandler,
            'play_page': GamePageHandler,
            'mixed_page': GamePageHandler,
            'password_protected_page': PasswordProtectedPageHandler
        }
        
        # 导航状态
        self.navigation_state = {
            'current_page_type': 'unknown',
            'last_action': None,
            'action_history': [],
            'popup_count': 0,
            'error_count': 0
        }
    
    @log_function_call
    @log_performance
    async def navigate_and_process(self, url: str, max_retries: int = 3) -> Dict[str, Any]:
        """
        导航到页面并进行完整处理
        
        Args:
            url: 目标URL
            max_retries: 最大重试次数
            
        Returns:
            Dict: 处理结果
        """
        try:
            self.logger.info(f"开始导航和处理页面: {url}")
            
            # 导航到页面
            await self.page.goto(url, wait_until="networkidle", timeout=30000)
            
            # 等待页面稳定
            await asyncio.sleep(2)
            
            # 执行完整的页面处理流程
            result = await self.process_current_page()
            
            # 更新导航状态
            self._update_navigation_state(result)
            
            result['url'] = url
            result['navigation_state'] = self.navigation_state.copy()
            
            self.logger.info(f"页面处理完成: {result.get('success', False)}")
            return result
            
        except Exception as e:
            self.logger.error(f"导航和处理页面失败: {str(e)}")
            self.navigation_state['error_count'] += 1
            
            if max_retries > 0:
                self.logger.info(f"重试导航，剩余次数: {max_retries - 1}")
                await asyncio.sleep(3)
                return await self.navigate_and_process(url, max_retries - 1)
            
            return {
                'success': False,
                'error': str(e),
                'url': url,
                'navigation_state': self.navigation_state.copy()
            }
    
    @log_function_call
    async def process_current_page(self) -> Dict[str, Any]:
        """
        处理当前页面
        
        Returns:
            Dict: 处理结果
        """
        try:
            # 第一步：检测页面类型
            detection_result = await self.page_detector.handle()
            page_type = detection_result.get('page_type', 'unknown')
            
            self.logger.info(f"检测到页面类型: {page_type}")
            
            # 第二步：处理弹窗
            popup_result = await self.handle_popups()
            
            # 第三步：根据页面类型执行相应操作
            page_action_result = await self.handle_page_by_type(page_type)
            
            # 第四步：检查下载对话框
            download_dialog_result = await self.handle_download_dialogs()
            
            # 汇总结果
            result = {
                'success': True,
                'page_type': page_type,
                'detection_result': detection_result,
                'popup_result': popup_result,
                'page_action_result': page_action_result,
                'download_dialog_result': download_dialog_result,
                'final_status': await self._get_final_page_status()
            }
            
            return result
            
        except Exception as e:
            self.logger.error(f"处理当前页面失败: {str(e)}")
            return {
                'success': False,
                'error': str(e),
                'page_type': 'error'
            }
    
    @log_function_call
    async def handle_popups(self) -> Dict[str, Any]:
        """
        处理页面弹窗
        
        Returns:
            Dict: 弹窗处理结果
        """
        try:
            self.logger.info("开始处理页面弹窗")
            
            # 使用弹窗处理器处理所有弹窗
            popup_result = await self.popup_handler.handle()
            
            # 更新弹窗计数
            self.navigation_state['popup_count'] += popup_result.get('closed_count', 0)
            
            # 记录操作
            self._record_action('handle_popups', popup_result)
            
            return popup_result
            
        except Exception as e:
            self.logger.error(f"处理弹窗失败: {str(e)}")
            return {'error': str(e), 'closed_count': 0}
    
    @log_function_call
    async def handle_page_by_type(self, page_type: str) -> Dict[str, Any]:
        """
        根据页面类型执行相应操作
        
        Args:
            page_type: 页面类型
            
        Returns:
            Dict: 操作结果
        """
        try:
            self.logger.info(f"根据页面类型执行操作: {page_type}")
            
            if page_type in self.page_handlers:
                # 使用对应的页面处理器
                handler_class = self.page_handlers[page_type]
                handler = handler_class(self.page)
                
                result = await handler.handle()
                
                # 如果是游戏页面，尝试点击下载按钮
                if page_type in ['game_page_a', 'game_page_b', 'download_page', 'mixed_page']:
                    download_result = await self._try_download_action(result)
                    result['download_action'] = download_result
                
                self._record_action(f'handle_{page_type}', result)
                return result
                
            elif page_type == 'unknown':
                # 对于未知页面，尝试通用处理
                return await self._handle_unknown_page()
                
            else:
                self.logger.warning(f"不支持的页面类型: {page_type}")
                return {
                    'success': False,
                    'message': f'不支持的页面类型: {page_type}',
                    'page_type': page_type
                }
                
        except Exception as e:
            self.logger.error(f"根据页面类型处理失败: {str(e)}")
            return {'success': False, 'error': str(e)}
    
    async def _try_download_action(self, page_result: Dict[str, Any]) -> Dict[str, Any]:
        """
        尝试执行下载操作
        
        Args:
            page_result: 页面处理结果
            
        Returns:
            Dict: 下载操作结果
        """
        try:
            # 检查是否有下载按钮
            if page_result.get('has_download_button'):
                download_button = page_result.get('download_button')
                
                if download_button:
                    # 点击下载按钮
                    click_result = await self.game_page_handler.click_download_button(download_button)
                    
                    if click_result.get('success'):
                        self.logger.info("成功点击下载按钮")
                        
                        # 等待可能出现的下载对话框
                        await asyncio.sleep(2)
                        
                        return {
                            'action': 'click_download_button',
                            'success': True,
                            'click_result': click_result
                        }
                    else:
                        self.logger.warning("点击下载按钮失败")
                        return {
                            'action': 'click_download_button',
                            'success': False,
                            'error': click_result.get('error')
                        }
            
            # 如果没有下载按钮，检查是否有游戏按钮
            elif page_result.get('has_play_button'):
                play_button = page_result.get('play_button')
                
                if play_button:
                    click_result = await self.game_page_handler.click_play_button(play_button)
                    
                    return {
                        'action': 'click_play_button',
                        'success': click_result.get('success'),
                        'click_result': click_result
                    }
            
            return {
                'action': 'none',
                'success': False,
                'message': '未找到可操作的按钮'
            }
            
        except Exception as e:
            self.logger.error(f"执行下载操作失败: {str(e)}")
            return {
                'action': 'error',
                'success': False,
                'error': str(e)
            }
    
    async def _handle_unknown_page(self) -> Dict[str, Any]:
        """
        处理未知页面类型
        
        Returns:
            Dict: 处理结果
        """
        try:
            self.logger.info("处理未知页面类型")
            
            # 尝试使用游戏页面处理器进行通用处理
            result = await self.game_page_handler.handle()
            
            # 如果找到了下载按钮，尝试点击
            if result.get('has_download_button'):
                download_action = await self._try_download_action(result)
                result['download_action'] = download_action
            
            result['handled_as'] = 'generic_game_page'
            return result
            
        except Exception as e:
            self.logger.error(f"处理未知页面失败: {str(e)}")
            return {
                'success': False,
                'error': str(e),
                'handled_as': 'error'
            }
    
    @log_function_call
    async def handle_download_dialogs(self) -> Dict[str, Any]:
        """
        处理下载对话框
        
        Returns:
            Dict: 对话框处理结果
        """
        try:
            self.logger.info("检查和处理下载对话框")
            
            # 检测下载对话框
            dialog_result = await self.download_dialog_handler.handle()
            
            if dialog_result.get('dialog_detected'):
                self.logger.info("检测到下载对话框并已处理")
                self._record_action('handle_download_dialog', dialog_result)
            else:
                self.logger.debug("未检测到下载对话框")
            
            return dialog_result
            
        except Exception as e:
            self.logger.error(f"处理下载对话框失败: {str(e)}")
            return {
                'error': str(e),
                'dialog_detected': False
            }
    
    async def _get_final_page_status(self) -> Dict[str, Any]:
        """
        获取最终页面状态
        
        Returns:
            Dict: 页面状态
        """
        try:
            return {
                'url': self.page.url,
                'title': await self.page.title(),
                'is_loaded': True,
                'has_errors': await self._check_page_errors(),
                'timestamp': asyncio.get_event_loop().time()
            }
        except Exception as e:
            self.logger.debug(f"获取页面状态失败: {str(e)}")
            return {'error': str(e)}
    
    async def _check_page_errors(self) -> bool:
        """
        检查页面是否有错误
        
        Returns:
            bool: 是否有错误
        """
        try:
            error_selectors = [
                '.error', '.alert-error', '.warning',
                'text="404"', 'text="500"', 'text="错误"'
            ]
            
            for selector in error_selectors:
                element = await self.page.query_selector(selector)
                if element and await element.is_visible():
                    return True
            
            return False
            
        except Exception as e:
            self.logger.debug(f"检查页面错误失败: {str(e)}")
            return False
    
    def _record_action(self, action: str, result: Dict[str, Any]) -> None:
        """
        记录操作历史
        
        Args:
            action: 操作名称
            result: 操作结果
        """
        try:
            action_record = {
                'action': action,
                'timestamp': asyncio.get_event_loop().time(),
                'success': result.get('success', False),
                'summary': self._get_action_summary(result)
            }
            
            self.navigation_state['action_history'].append(action_record)
            self.navigation_state['last_action'] = action
            
            # 保持历史记录不超过10条
            if len(self.navigation_state['action_history']) > 10:
                self.navigation_state['action_history'] = self.navigation_state['action_history'][-10:]
                
        except Exception as e:
            self.logger.debug(f"记录操作历史失败: {str(e)}")
    
    def _get_action_summary(self, result: Dict[str, Any]) -> str:
        """
        获取操作摘要
        
        Args:
            result: 操作结果
            
        Returns:
            str: 操作摘要
        """
        try:
            if 'closed_count' in result:
                return f"关闭了{result['closed_count']}个弹窗"
            elif 'download_button' in result:
                return f"找到下载按钮: {result.get('has_download_button', False)}"
            elif 'dialog_detected' in result:
                return f"检测到对话框: {result['dialog_detected']}"
            else:
                return f"操作完成: {result.get('success', False)}"
        except:
            return "操作完成"
    
    def _update_navigation_state(self, result: Dict[str, Any]) -> None:
        """
        更新导航状态
        
        Args:
            result: 处理结果
        """
        try:
            self.navigation_state['current_page_type'] = result.get('page_type', 'unknown')
            
            if not result.get('success', False):
                self.navigation_state['error_count'] += 1
                
        except Exception as e:
            self.logger.debug(f"更新导航状态失败: {str(e)}")
    
    @log_function_call
    async def wait_for_navigation(self, timeout: int = 30000) -> bool:
        """
        等待页面导航完成
        
        Args:
            timeout: 超时时间（毫秒）
            
        Returns:
            bool: 是否导航成功
        """
        try:
            await self.page.wait_for_load_state("networkidle", timeout=timeout)
            return True
        except Exception as e:
            self.logger.warning(f"等待导航超时: {str(e)}")
            return False
    
    def get_navigation_summary(self) -> Dict[str, Any]:
        """
        获取导航摘要
        
        Returns:
            Dict: 导航摘要
        """
        return {
            'current_page_type': self.navigation_state['current_page_type'],
            'total_actions': len(self.navigation_state['action_history']),
            'popup_count': self.navigation_state['popup_count'],
            'error_count': self.navigation_state['error_count'],
            'last_action': self.navigation_state['last_action'],
            'recent_actions': self.navigation_state['action_history'][-3:] if self.navigation_state['action_history'] else []
        }